package com.gs.process.admin.service;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gs.process.model.Process;
import com.gs.process.model.ProcessNode;
import com.gs.process.admin.mapper.ProcessMapper;
import com.gs.process.admin.utils.ValidateUtil;
import com.shallowUniverse.utils.AssertUtil;
import com.shallowUniverse.utils.PrimaryKeyUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author gs
 * @date create in 2020/12/11 17:05
 */
@Service
public class ProcessService extends ServiceImpl<ProcessMapper, Process> {

    @Resource
    private ProcessMapper processMapper;
    @Resource
    private ProcessNodeService processNodeService;
    @Resource
    private ApprovalService approvalService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(Process process) {
        AssertUtil.service().notNull(process, "流程为空");
        if (ObjectUtils.isEmpty(process.getCreateDate())) {
            process.setCreateDate(DateUtil.now());
        }
        //设置主键
        process.setSid(PrimaryKeyUtil.generate());
        int total = processMapper.insert(process);
        process.getProcessNodes().forEach(processNodeDefinition -> {
            processNodeDefinition.setProcessId(process.getSid());
        });
        processNodeService.saveBatch(process.getProcessNodes());
        return total > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean remove(List<Long> ids) {
        //判斷是否传递了id
        AssertUtil.service().notNull(ids, "请传递正确的参数");
        //校验是否还存在未完成的流程
        AssertUtil.service().isTrue(ValidateUtil.processCompletedByProcess(ids, approvalService), "存在未完成的流程");
        //删除流程
        processMapper.deleteBatchIds(ids);
        //删除节点
        processNodeService.remove(new UpdateWrapper<ProcessNode>().lambda().in(ProcessNode::getProcessId, ids));

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean update(Process process) {
        //判斷是否传递了id
        AssertUtil.service().notNull(process, "请传递正确的参数");
        //校验是否还存在未完成的流程
        AssertUtil.service().isTrue(ValidateUtil.processCompletedByProcess(Collections.singletonList(process.getSid()), approvalService), "存在未完成的流程");
        //修改流程
        int total = processMapper.updateById(process);
        //拿到之前的所有节点
        List<Long> processNodeDefinitions = processNodeService.list(
                new QueryWrapper<ProcessNode>().lambda()
                        .eq(ProcessNode::getProcessId, process.getSid())
        ).stream().map(ProcessNode::getSid).collect(Collectors.toList());
        //拿到新增集合
        List<ProcessNode> saveList = process.getProcessNodes().stream().filter(item -> ObjectUtils.isEmpty(item.getSid())).collect(Collectors.toList());
        //拿到修改集合
        List<ProcessNode> updateList = process.getProcessNodes().stream().filter(item -> !ObjectUtils.isEmpty(item.getSid())).collect(Collectors.toList());
        //拿到删除集合
        List<Long> deleteList = processNodeDefinitions.stream().filter(id -> updateList.stream().noneMatch(item -> item.getSid().equals(id))).collect(Collectors.toList());
        //判断是否需要新增
        if (!CollectionUtils.isEmpty(saveList)) {
            //设置sid
            saveList.forEach(item -> item.setSid(PrimaryKeyUtil.generate()));
            processNodeService.saveBatch(saveList);
        }
        //判断是否需要修改
        if (!CollectionUtils.isEmpty(updateList)) {
            processNodeService.updateBatchById(updateList);
        }
        //判断是否需要删除
        if (!CollectionUtils.isEmpty(deleteList)) {
            processNodeService.removeByIds(deleteList);
        }
        return total > 0;
    }
}
